package com.mind.invoice.controller;

import com.mind.common.annotation.Log;
import com.mind.common.config.MindConfig;
import com.mind.common.constant.Constants;
import com.mind.common.core.domain.AjaxResult;
import com.mind.common.enums.BusinessType;
import com.mind.common.utils.StringUtils;
import com.mind.common.utils.file.FileUploadUtils;
import com.mind.common.utils.file.FileUtils;
import com.mind.common.utils.poi.ExcelUtil;
import com.mind.common.web.controller.BaseController;
import com.mind.common.web.page.TableDataInfo;
import com.mind.invoice.domain.AjFileLibrary;
import com.mind.invoice.domain.AjFileLibraryAttach;
import com.mind.invoice.service.IAjFileLibraryAttachService;
import com.mind.invoice.service.IAjFileLibraryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 稽核文件库管理Controller
 *
 * @author xp
 * @date 2025-05-08
 */
@RestController
@RequestMapping("/invoice/library")
@Tag(name = "稽核文件库管理", description = "稽核文件库管理")
public class AjFileLibraryController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(AjFileLibraryController.class);

    @Autowired
    private IAjFileLibraryService ajFileLibraryService;
    @Autowired
    private IAjFileLibraryAttachService ajFileLibraryAttachService;
    private static final String FILE_DELIMETER = ",";

    /**
     * 查询文件库列表
     */
    //@PreAuthorize("@ss.hasPermi('invoice:library:list')")
    @GetMapping("/list")
    @Operation(summary = "查询文件库列表", description = "查询文件库列表")
    public TableDataInfo list(AjFileLibrary ajFileLibrary) {
        startPage();
        List<AjFileLibrary> list = ajFileLibraryService.selectAjFileLibraryList(ajFileLibrary);
        return getDataTable(list);
    }

    /**
     * 导出文件库列表
     */
    //@PreAuthorize("@ss.hasPermi('invoice:library:export')")
    @Log(title = "文件库", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @Operation(summary = "导出文件库列表", description = "查询文件库列表")
    public void export(HttpServletResponse response, AjFileLibrary ajFileLibrary) {
        List<AjFileLibrary> list = ajFileLibraryService.selectAjFileLibraryList(ajFileLibrary);
        ExcelUtil<AjFileLibrary> util = new ExcelUtil<AjFileLibrary>(AjFileLibrary.class);
        util.exportExcel(response, list, "文件库数据");
    }

    /**
     * 获取文件库详细信息
     */
    //@PreAuthorize("@ss.hasPermi('invoice:library:query')")
    @GetMapping(value = "/{id}")
    @Operation(summary = "获取文件库详细信息", description = "获取文件库详细信息")
    public AjaxResult getInfo(@Parameter(description = "文件库Id", required = true) @PathVariable("id") Long id) {
        AjFileLibrary ajFileLibrary = ajFileLibraryService.selectAjFileLibraryById(id);
        if (ajFileLibrary == null) {
            return success();
        }
        AjFileLibraryAttach ajFileLibraryAttach = new AjFileLibraryAttach();
        ajFileLibraryAttach.setAjFileLibraryId(ajFileLibrary.getId());
        List<AjFileLibraryAttach> ajFileLibraryAttaches =
                ajFileLibraryAttachService.selectAjFileLibraryAttachList(ajFileLibraryAttach);
        ajFileLibrary.setAttachFileList(ajFileLibraryAttaches);
        return success(ajFileLibrary);
    }

    /**
     * 新增文件库
     */
    //@PreAuthorize("@ss.hasPermi('invoice:library:add')")
    @Log(title = "文件库", businessType = BusinessType.INSERT)
    @PostMapping
    @Operation(summary = "新增文件库", description = "新增文件库")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult add(@RequestBody AjFileLibrary ajFileLibrary) {
        int i = ajFileLibraryService.insertAjFileLibrary(ajFileLibrary);
        Long id = ajFileLibrary.getId();
        List<AjFileLibraryAttach> insertAjFileLibraryAttach = new ArrayList<>();
        if (!ajFileLibrary.getAttachFileList().isEmpty()) {
            for (AjFileLibraryAttach ajFileLibraryAttach : ajFileLibrary.getAttachFileList()) {
                ajFileLibraryAttach.setAjFileLibraryId(id);
                insertAjFileLibraryAttach.add(ajFileLibraryAttach);
            }
            ajFileLibraryAttachService.insertAjFileLibraryAttachBatch(insertAjFileLibraryAttach);
        }
        return toAjax(i);
    }

    /**
     * 修改文件库
     */
    //@PreAuthorize("@ss.hasPermi('invoice:library:edit')")
    @Log(title = "文件库", businessType = BusinessType.UPDATE)
    @PutMapping
    @Operation(summary = "修改文件库", description = "修改文件库")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult edit(@RequestBody AjFileLibrary ajFileLibrary) {
        int i = ajFileLibraryService.updateAjFileLibrary(ajFileLibrary);
        Long[] ids = new Long[]{
                ajFileLibrary.getId()
        };
        ajFileLibraryAttachService.deleteAjFileLibraryAttachByAjFileIds(ids);
        List<AjFileLibraryAttach> insertAjFileLibraryAttach = new ArrayList<>();
        if (!ajFileLibrary.getAttachFileList().isEmpty()) {
            for (AjFileLibraryAttach ajFileLibraryAttach : ajFileLibrary.getAttachFileList()) {
                ajFileLibraryAttach.setAjFileLibraryId(ajFileLibrary.getId());
                insertAjFileLibraryAttach.add(ajFileLibraryAttach);
            }
            ajFileLibraryAttachService.insertAjFileLibraryAttachBatch(insertAjFileLibraryAttach);
        }

        return toAjax(i);
    }

    /**
     * 删除文件库
     */
    //@PreAuthorize("@ss.hasPermi('invoice:library:remove')")
    @Log(title = "文件库", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @Operation(summary = "删除文件库", description = "删除文件库")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult remove(@Parameter(description = "文件库Id", required = true) @PathVariable Long[] ids) {
        int i = ajFileLibraryService.deleteAjFileLibraryByIds(ids);
        ajFileLibraryAttachService.deleteAjFileLibraryAttachByAjFileIds(ids);

        return toAjax(i);
    }

    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete   是否删除
     */
    @GetMapping("/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
        try {
            if (!FileUtils.checkAllowDownload(fileName)) {
                throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = MindConfig.getProfileAj() + fileName;
            filePath = filePath.replace("//", "/");


            String mimeType = Files.probeContentType(Paths.get(realFileName)); // 自动检测MIME类型

// 1. 文件名编码处理（确保符合RFC 5987规范）
            String encodedFileName = FileUtils.percentEncode(realFileName); // 空格处理优化

// 2. 构建Content-Disposition（兼容现代和旧浏览器）
            StringBuilder disposition = new StringBuilder();
            if (isPreviewable(mimeType)) {
                disposition.append("inline");
            } else {
                disposition.append("attachment"); // 不可预览类型强制下载
            }
            disposition.append("; filename=\"")
                    .append(realFileName.replace("\"", "%22")) // 处理双引号
                    .append("\"; filename*=utf-8''")
                    .append(encodedFileName);

// 3. 设置响应头（关键修改点）
            response.reset(); // 清除可能存在的冲突头信息
            response.setHeader("Content-Disposition", disposition.toString());
            response.setContentType(mimeType != null ? mimeType : MediaType.APPLICATION_OCTET_STREAM_VALUE);

// 4. 跨域头配置（需与CORS配置统一）
            response.addHeader("Access-Control-Expose-Headers", "Content-Disposition, Download-Filename");
            response.setHeader("Download-Filename", encodedFileName); // 自定义文件名头



           /* String percentEncodedFileName = FileUtils.percentEncode(realFileName);
            StringBuilder contentDispositionValue = new StringBuilder();
            contentDispositionValue.append("inline;filename=")
                    .append(percentEncodedFileName)
                    .append(";")
                    .append("filename*=")
                    .append("utf-8''")
                    .append(percentEncodedFileName);

            response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
            response.setHeader("Content-disposition", contentDispositionValue.toString());
            response.setHeader("download-filename", percentEncodedFileName);
            response.setHeader("Content-Type", String.valueOf(MediaType.IMAGE_PNG));
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
*/
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete) {
                FileUtils.deleteFile(filePath);
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    // 定义可预览的 MIME 类型白名单
    private boolean isPreviewable(String mimeType) {
        return List.of(
                "image/png",
                "image/jpeg",
                "application/pdf",
                "text/plain"
        ).contains(mimeType);
    }

    /**
     * 通用上传请求（单个）
     */
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Operation(summary = "文件上传", description = "文件上传")
    public AjaxResult uploadFile(@Parameter(description = "文件", required = true) @RequestPart("file") MultipartFile file) throws Exception {
        try {
            // 上传文件路径
            //String filePrefix = "mind"+ DateUtils.dateTime();
            String filePath = MindConfig.getProfileAj();

            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String fileName2 = fileName.replace("//", "/");
            String url = MindConfig.getHost() + "/api/invoice/library/download?fileName=" + fileName2;
            AjaxResult ajax = AjaxResult.success(new HashMap<String, Object>() {
                {
                    put("url", url);
                    put("fileName", fileName2);
                    put("newFileName", FileUtils.getName(fileName2));
                    put("originalFilename", file.getOriginalFilename());
                }
            });


            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 通用上传请求（多个）
     */
    @PostMapping(value = "/uploads", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Operation(summary = "多个文件上传", description = "可多文件上传")
    public AjaxResult uploadFiles(@Parameter(description = "文件", required = true) @RequestPart("files") List<MultipartFile> files) throws Exception {
        try {
            // 上传文件路径
            //String filePrefix = "mind"+ DateUtils.dateTime();
            String filePath = MindConfig.getProfileAj();
            List<String> urls = new ArrayList<String>();
            List<String> fileNames = new ArrayList<String>();
            List<String> newFileNames = new ArrayList<String>();
            List<String> originalFilenames = new ArrayList<String>();
            for (MultipartFile file : files) {
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                String url = MindConfig.getHost() + "/api/customer/file" + fileName;
                urls.add(url);
                fileNames.add(fileName);
                newFileNames.add(FileUtils.getName(fileName));
                originalFilenames.add(file.getOriginalFilename());
            }
            AjaxResult ajax = AjaxResult.success(new HashMap<String, Object>() {
                {
                    put("urls", StringUtils.join(urls, FILE_DELIMETER));
                    put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
                    put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
                    put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
                }
            });

            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 本地资源通用下载
     */
    @GetMapping("/download/resource")
    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        try {
            if (!FileUtils.checkAllowDownload(resource)) {
                throw new Exception(StringUtils.format("资源文件({})非法，不允许下载。 ", resource));
            }
            // 本地资源路径
            String localPath = MindConfig.getProfile();
            // 数据库资源地址
            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }
}
